package com.booway.threadtemp.factoryimpl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.booway.threadtemp.exception.FactoryException;
import com.booway.threadtemp.exception.MachineException;
import com.booway.threadtemp.factory.FactoryContext;
import com.booway.threadtemp.factory.IFactory;
import com.booway.threadtemp.product.HasHandStock;
import com.booway.threadtemp.stock.StockPackage;
import com.booway.threadtemp.util.ThreadTempUtil;
import com.personal.core.delay.CreateAndExpiry;
import com.personal.core.delay.DelayCache;

/**
 * 
 * 抽象的原料工厂
 * 
 * 该工厂整合了原料，产品，机器，在使用时只需要定义一个类实现该类即可。
 * 将机器私有化到工厂内部，客户端程序员使用时只需要创建工厂实例即可，不需要创建原料，产品，机器等。
 * @author cuibo
 * @param <S>
 * @param <P>
 */

public abstract class AbstractFactory<S, P> implements IFactory<S, P>
{
    
    /** 等待原料状态 */
    public static final short STATE_WAIT = 0;

    /** 等待原料但是仍有原料正在处理 */
    public static final short STATE_WAIT_DO = 1;

    /** 工作状态 */
    public static final short STATE_DO = 2;

    /** 暂停 */
    public static final short STATE_STOP = 3;

    /** 关闭 */
    public static final short STATE_DOWN = 4;

    /** 工厂上下文 */
    private FactoryContext factoryContext;

    /** 原料 */
    protected BlockingQueue<S> stockQueue;

    /** 计数器 */
    private Map<S, CountDownLatch> stockLatch;

    /** 正在处理的原料 */
    private Queue<S> isHandStockQueue;

    /** 产品 */
    private Map<S, HasHandStock<S, P>> productMap;

    /** 已经处理完原料  */
    private BlockingQueue<HasHandStock<S, P>> hasHandStockQueue;

    /** 处理失败的数据 */
    private BlockingQueue<HasHandStock<S, P>> exceptionHandStockQueue;

    /** 原料包计数器key:原料包ID value：原料包下的原料集合 */
    private Map<String, Set<S>> stockPackageLatch;
    /** 每个原料对应的原料包ID */
    private Map<S, String> stockPackageReRelation;

    /** 机器是否敏感 */
    private volatile boolean machineSensitive;

    /** 工人 */
    protected Worker worker;

    /** 生产机器 */
    private volatile Machine machine;

    /** 产品保质期(单位毫秒) */
    private volatile long productExpirydate;

    /** 异常产品保质期(单位毫秒) */
    private volatile long exceptionExpirydate;

    /** 上下文保质期(单位毫秒) */
    private volatile long contextExpirydate;

    /** 该机器的最大同步数量（及同时处理原料的个数） */
    private int maxSyncCount;

    private static final long DEFAULT_PRODUCTEXPIRYDATE = TimeUnit.HOURS.toMillis(1);
    private static final long DEFAULT_EXCEPTIONEXPIRYDATE = TimeUnit.HOURS.toMillis(1);
    private static final long DEFAULT_CONTEXTEXPIRYDATE = TimeUnit.HOURS.toMillis(1);

    public AbstractFactory()
    {
        this(1);
    }

    public AbstractFactory(int maxSyncCount)
    {
        this(maxSyncCount, DEFAULT_PRODUCTEXPIRYDATE, DEFAULT_EXCEPTIONEXPIRYDATE, DEFAULT_CONTEXTEXPIRYDATE);
    }

    public AbstractFactory(int maxSyncCount, long productExpirydate, long exceptionExpirydate, long contextExpirydate)
    {
        this(maxSyncCount, null, productExpirydate, exceptionExpirydate, contextExpirydate);
    }
    
    public AbstractFactory(int maxSyncCount, ExecutorService service, long productExpirydate, long exceptionExpirydate, long contextExpirydate)
    {
        this.maxSyncCount = maxSyncCount;
        this.productExpirydate = productExpirydate;
        this.exceptionExpirydate = exceptionExpirydate;
        this.contextExpirydate = contextExpirydate;
        // 初始化必要资源
        initResource();
        if (service != null)
        {
            this.worker.setExecutorService(service);
        }
        // 工人开始工作
        this.worker.startWork();
    }

    /**
     * 初始化必要资源
     */
    private void initResource()
    {
        // 初始化队列种类和资源
        initQueueTypeAndResource();
        this.productMap = new ConcurrentHashMap<S, HasHandStock<S, P>>();
        this.stockLatch = new ConcurrentHashMap<S, CountDownLatch>();
        this.stockPackageLatch = new ConcurrentHashMap<String, Set<S>>();
        this.stockPackageReRelation = new ConcurrentHashMap<S, String>();
        this.hasHandStockQueue = new DelayQueue<HasHandStock<S, P>>();
        this.isHandStockQueue = new LinkedBlockingQueue<S>();
        this.exceptionHandStockQueue = new DelayQueue<HasHandStock<S, P>>();
        this.worker = this.new Worker();
        this.machine = this.new Machine();
        this.factoryContext = new FactoryContextImpl();
    }

    /**
     * 初始化队列种类和资源
     */
    protected abstract void initQueueTypeAndResource();

    /**
     * 获取下一个原料：由Machine调用，所以一定是单线程调用
     * @return
     * @throws InterruptedException
     */
    protected abstract S getNextStock() throws InterruptedException;

    /**
     * 钩子方法
     * @param s
     */
    protected void doStockStartHook(S s)
    {
    }

    /**
     * 钩子方法
     * @param s
     * @param result
     * @param cause
     */
    protected void doStockCompleteHook(S s, P result, Throwable cause)
    {
    }

    /**
     * 获取上下文
     * @return
     */
    public FactoryContext getFactoryContext()
    {
        return factoryContext;
    }

    /**
     * 设置上下文
     * @param factoryContext
     */
    public void setFactoryContext(FactoryContext factoryContext)
    {
        this.factoryContext = factoryContext;
    }

    /**
     * 获取当前工厂状态
     * @return
     */
    public short getFactoryState()
    {
        return this.worker.getFactoryState();
    }

    /**
     * 添加原料到工厂
     * @param s
     * @throws FactoryException
     */
    @Override
    public synchronized boolean addStock(S s) throws FactoryException
    {
        return this.worker.addStock(s);
    }

    /**
     * 添加原料到工厂
     * @param stockPackage
     * @throws FactoryException
     */
    @Override
    public synchronized boolean addStockPackage(StockPackage<S> stockPackage) throws FactoryException
    {
        return this.worker.addStockPackage(stockPackage);
    }

    /**
     * 批量添加原料到工厂
     * @param entrys
     * @throws FactoryException
     */
    @Override
    public synchronized boolean addAllStock(Collection<S> entrys) throws FactoryException
    {
        return this.worker.addAllStock(entrys, null, false);
    }

    /**
     * 获取原料对应的产品(设置超时)
     * @param s
     * @param wait
     * @param unit
     * @throws TimeoutException 
     */
    @Override
    public P getHandleProdct(S s, long wait, TimeUnit unit) throws TimeoutException
    {
        return this.worker.getHandleProdct(s, wait, unit);
    }

    /**
     * 获取原料对应的产品
     * @param s
     * @return
     */
    @Override
    public P getHandleProdct(S s)
    {
        return this.worker.getHandleProdct(s);
    }

    /**
     * 获取原料对应的处理完成原料
     * @param s
     * @return
     */
    @Override
    public HasHandStock<S, P> getHasHandStock(S s)
    {
        return this.worker.getHasHandStock(s);
    }

    /**
     * 获取原料对应的处理完成原料
     * @param s
     * @param wait
     * @param unit
     * @return
     * @throws TimeoutException 
     */
    @Override
    public HasHandStock<S, P> getHasHandStock(S s, long wait, TimeUnit unit) throws TimeoutException
    {
        return this.worker.getHasHandStock(s, wait, unit);
    }

    /**
     * 检查原料是否处理完
     * @param s
     * @return
     */
    @Override
    public boolean checkStockHasDown(S s)
    {
        return this.worker.checkStockHasDown(s);
    }

    /**
     * 检查原料包是否处理完
     * @param stockPackageId
     * @return
     */
    @Override
    public boolean checkStockPackageHasDown(String stockPackageId)
    {
        return this.worker.checkStockPackageHasDown(stockPackageId);
    }

    /**
     * 等待原料加工完成
     * @param s
     * @param wait   等待超时设置
     * @param unit
     * @throws TimeoutException 
     */
    @Override
    public void waitStockDown(S s, long wait, TimeUnit unit) throws TimeoutException
    {
        this.worker.waitStockDown(s, wait, unit);
    }

    /**
     * 等待原料包加工完成
     * @param stockPackageId
     * @param wait   等待超时设置
     * @param unit
     * @throws TimeoutException 
     */
    @Override
    public void waitStockPackageDown(String stockPackageId, long wait, TimeUnit unit) throws TimeoutException
    {
        this.worker.waitStockPackageDown(stockPackageId, wait, unit);
    }

    /**
     * 等待原料包加工完成
     * @param stockPackageId
     */
    @Override
    public void waitStockPackageDown(String stockPackageId)
    {
        this.worker.waitStockPackageDown(stockPackageId);
    }

    /**
     * 等待原料加工完成（一直等待）
     * @param s
     * @return
     */
    @Override
    public void waitStockDown(S s)
    {
        this.worker.waitStockDown(s);
    }

    /**
     * 等待整个工厂的原料全部完成
     */
    @Override
    public void waitFactoryDown()
    {
        this.worker.waitFactoryDown();
    }

    /**
     * 等待整个工厂的原料全部完成
     * @param wait
     * @param unit
     * @throws TimeoutException 
     */
    @Override
    public void waitFactoryDown(long wait, TimeUnit unit) throws TimeoutException
    {
        this.worker.waitFactoryDown(wait, unit);
    }

    /**
     * 批量移除原料（如果原料已经送入机器处理则移除失败）
     * @param ts
     * @return  返回移除成功的原料
     */
    @Override
    public List<S> removeStock(List<S> ts)
    {
        if (ThreadTempUtil.isEmpty(ts))
        {
            return null;
        }
        List<S> result = new ArrayList<S>();
        for (S s : ts)
        {
            S remove = this.worker.removeStock(s);
            if (remove != null)
            {
                result.add(remove);
            }
        }
        return result;
    }
    
    /**
     * 批量移除异常原料（如果原料已经送入机器处理则移除失败）
     * @param ts
     * @return  返回移除成功的原料
     */
    @Override
    public List<S> removeExceptionStock(List<S> ts)
    {
        if (ThreadTempUtil.isEmpty(ts))
        {
            return null;
        }
        List<S> result = new ArrayList<S>();
        for (S s : ts)
        {
            S remove = this.worker.removeExceptionStock(s);
            if (remove != null)
            {
                result.add(remove);
            }
        }
        return result;
    }
    
    /**
     * 移除指定原料
     * @param s
     * @return
     */
    @Override
    public boolean removeStock(S s)
    {
        if (s == null)
        {
            return false;
        }
        return this.worker.removeStock(s) != null;
    }

    /**
     * 移除指定异常原料
     * @param s
     * @return
     */
    @Override
    public boolean removeExceptionStock(S s)
    {
        if (s == null)
        {
            return false;
        }
        return this.worker.removeExceptionStock(s) != null;
    }
    
    /**
     * 重新提交出现异常的原料
     * @return
     * @throws FactoryException 
     */
    @Override
    public synchronized boolean reHandExceptionStock() throws FactoryException
    {
        return worker.reHandExceptionStock();
    }
    
    /**
     * 重新提交出现异常的原料
     * @param s
     * @return
     * @throws FactoryException 
     */
    @Override
    public synchronized boolean reHandExceptionStock(S s) throws FactoryException
    {
        return worker.reHandExceptionStock(s);
    }

    /**
     * 获取正在等待处理的原料队列
     * @return
     */
    @Override
    public Queue<S> getWaitingQueue()
    {
        return new LinkedList<S>(stockQueue);
    }

    /**
     * 获取正在正在处理的
     * @return
     */
    @Override
    public Queue<S> getHandingQueue()
    {
        return new LinkedList<S>(isHandStockQueue);
    }

    /**
     * 获取处理出现异常的原料（持有失败原因）
     * @return
     */
    @Override
    public Queue<HasHandStock<S, P>> getExceptionQueueWithCause()
    {
        if (exceptionHandStockQueue == null || exceptionHandStockQueue.isEmpty())
        {
            return null;
        }
        return new LinkedList<HasHandStock<S, P>>(exceptionHandStockQueue);
    }

    /**
     * 获取处理出现异常的原料
     * @return
     */
    @Override
    public Queue<S> getExceptionQueue()
    {
        if (exceptionHandStockQueue == null || exceptionHandStockQueue.isEmpty())
        {
            return null;
        }
        LinkedList<S> result = new LinkedList<S>();
        for (HasHandStock<S, P> s : exceptionHandStockQueue)
        {
            result.add(s.getStock());
        }
        return result;
    }

    /**
     * 获取已经处理的原料
     * （过期的原料获取不到，应为所有数据均在内存中，不可能无限存储数据，除非持久化）
     * @return
     */
    @Override
    public Queue<S> getHasHandQueue()
    {
        if (hasHandStockQueue == null || hasHandStockQueue.isEmpty())
        {
            return null;
        }
        LinkedList<S> result = new LinkedList<S>();
        for (HasHandStock<S, P> s : hasHandStockQueue)
        {
            result.add(s.getStock());
        }
        return result;
    }

    /**
     * 获取已经处理的原料,并包含其结果信息
     * @return
     */
    @Override
    public Queue<HasHandStock<S, P>> getHasHandQueueWithProduct()
    {
        if (hasHandStockQueue == null || hasHandStockQueue.isEmpty())
        {
            return null;
        }
        return new LinkedList<HasHandStock<S, P>>(hasHandStockQueue);
    }

    /**
     * 暂停工作（已经启动的子线程不会受到影响）
     * @throws FactoryException 
     */
    @Override
    public void stopHandle() throws FactoryException
    {
        this.worker.stopHandle();
    }

    /**
     * 暂停工作（会将正在运行的子线程也暂停，但是并不能保证暂停成功！）
     * @throws FactoryException 
     */
    @Override
    public void stopHandleNow() throws FactoryException
    {
        this.worker.stopHandleNow();
    }

    /**
     * 重启工作
     * @throws FactoryException 
     */
    @Override
    public void restartHandle() throws FactoryException
    {
        this.worker.restartHandle();
    }

    /**
     * 清除整个工厂
     */
    @Override
    public void clearFactory()
    {
        this.worker.clearFactory();
    }

    /**
     * 关闭
     */
    @Override
    public void shutDown()
    {
        this.worker.shutDown();
    }

    /**
     * 重新设置最大并发数
     * @param maxSyncCount
     * @throws FactoryException
     */
    public void reSetMaxSyncCount(int maxSyncCount) throws FactoryException
    {
        this.worker.reSetMaxSyncCount(maxSyncCount);
    }
    
    /**
     * 注入外部的ExecutorService
     * @param service
     */
    public void setExecutorService(ExecutorService service)
    {
        this.worker.setExecutorService(service);
    }

    public int getMaxSyncCount()
    {
        return maxSyncCount;
    }

    public long getProductExpirydate()
    {
        return productExpirydate;
    }

    public void setProductExpirydate(long productExpirydate)
    {
        this.productExpirydate = productExpirydate;
    }

    public long getExceptionExpirydate()
    {
        return exceptionExpirydate;
    }

    public void setExceptionExpirydate(long exceptionExpirydate)
    {
        this.exceptionExpirydate = exceptionExpirydate;
    }

    public long getContextExpirydate()
    {
        return contextExpirydate;
    }

    public void setContextExpirydate(long contextExpirydate)
    {
        this.contextExpirydate = contextExpirydate;
    }

    public boolean isMachineSensitive()
    {
        return machineSensitive;
    }

    public void setMachineSensitive(boolean machineSensitive)
    {
        this.machineSensitive = machineSensitive;
    }
    
    /**
     * 机器
     * @author cuibo
     *
     */
    final class Machine extends Thread
    {

        /** 死亡标记 */
        private volatile boolean death;

        /** 启动标记 */
        private boolean start;

        /** 暂停标记 */
        private boolean wait;

        /** 子线程暂停标记 */
        private boolean childWait;

        /** 锁（用于启动，暂停，重启，属性变更等操作的同步，等待，唤醒） */
        private Lock lock = new ReentrantLock();

        /** 该机器正在处理资源数（原子操作） */
        private AtomicInteger isDoingCount;

        /** 子线程线程池 */
        private ExecutorService service;

        /** 是否是单线程处理  */
        private AtomicBoolean isSingle;

        private Machine()
        {
            this.setUncaughtExceptionHandler(this.new MachineUnCaughtExceptionHandler());
            this.isDoingCount = new AtomicInteger(0);
            this.isSingle = new AtomicBoolean(false);
        }

        private Machine(Machine oldMachine)
        {
            this.setUncaughtExceptionHandler(this.new MachineUnCaughtExceptionHandler());
            this.isDoingCount = oldMachine.isDoingCount;
            this.isSingle = oldMachine.isSingle;
        }

        @Override
        public void run()
        {
            // maxSyncCount的合法性校验
            if (maxSyncCount <= 0)
            {
                // 设置成为CPU核心数的两倍
                maxSyncCount = Runtime.getRuntime().availableProcessors() << 1;
            }
            if (maxSyncCount > 1 && service == null)
            {
                // 新建子线程池
                service = Executors.newCachedThreadPool();
                ThreadPoolExecutor thisService = (ThreadPoolExecutor) service;
                // 设置拒绝任务处理
                thisService.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            }
            isSingle.set(maxSyncCount <= 1);
            while (true)
            {
                if (death)
                {
                    break;
                }
                if (isSingle.get())
                {
                    // 单线程处理
                    doSingle();
                } else
                {
                    // 多线程采用新建子线程处理
                    doMulti();
                }
                if (death)
                {
                    break;
                }
            }
        }

        /**
         * 同时处理多个原料
         */
        private void doMulti()
        {
            final S stock = worker.getStock();
            if (stock != null && worker.doStockStart(stock))
            {
                service.submit(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        doSingleImpl(stock);
                    }
                });
            }
        }

        /**
         * 处理单个原料
         */
        private void doSingle()
        {
            S stock = worker.getStock();
            if (stock != null && worker.doStockStart(stock))
            {
                doSingleImpl(stock);
            }
        }

        /**
         * 处理单个原料实现
         * @param stock
         */
        private void doSingleImpl(S stock)
        {
            P result = null;
            Throwable cause = null;
            try
            {
                // 只对敏感的机器添加此操作
                if (machineSensitive)
                {
                    // 检查子线程是否被暂停
                    worker.checkChildWait();
                }
                try
                {
                    // 钩子方法
                    doStockStartHook(stock);
                    // 加工stock
                    result = handleStock(stock);
                } catch (Throwable e)
                {
                    cause = e;
                }
                // 只对敏感的机器添加此操作
                if (machineSensitive)
                {
                    // 检查子线程是否被暂停
                    worker.checkChildWait();
                }
            } finally
            {
                worker.doStockComplete(stock, result, cause);
            }
        }

        /**
         * 取消该机器工作
         */
        private void shutDown()
        {
            death = true;
            if (service != null)
            {
                // 关闭线程池
                service.shutdown();
            }
        }

        /**
         * 暂停该机器工作
         * @throws MachineException 
         */
        private void stopHandle() throws MachineException
        {
            lock.lock();
            try
            {
                checkCanWork();
                if (wait)
                {
                    throw new MachineException("改机器已经处于暂停状态！");
                }
                wait = true;
            } finally
            {
                lock.unlock();
            }
        }

        /**
         * 暂停该机器工作（尽最大能力暂停子线程）
         * @throws MachineException 
         */
        private void stopHandleNow() throws MachineException
        {
            lock.lock();
            try
            {
                checkCanWork();
                if (wait)
                {
                    throw new MachineException("改机器已经处于暂停状态！");
                }
                wait = true;
                childWait = true;
            } finally
            {
                lock.unlock();
            }
        }

        /**
         * 重新开始
         * @throws MachineException 
         */
        private void restartHandle() throws MachineException
        {
            lock.lock();
            try
            {
                checkCanWork();
                if (!wait)
                {
                    throw new MachineException("改机器已经处于启动状态！");
                }
                wait = false;
                childWait = false;
                worker.signWait();
            } finally
            {
                lock.unlock();
            }
        }

        /**
         * 查看当前机器能否工作
         * @throws MachineException 
         */
        private void checkCanWork() throws MachineException
        {
            if (!start)
            {
                throw new MachineException("当前机器还未启动！");
            }
            if (death)
            {
                throw new MachineException("当前机器已经死亡！");
            }
            if (!this.isAlive())
            {
                throw new MachineException("当前机器已经死亡！");
            }
        }

        /**
         * 机器启动
         */
        private void startHandle()
        {
            lock.lock();
            try
            {
                if (start)
                {
                    return;
                }
                // 启动
                this.start();
                start = true;
            } finally
            {
                lock.unlock();
            }
        }

        /**
         * 获取该机器的计数器
         * @return
         */
        private AtomicInteger getIsDoingCount()
        {
            return isDoingCount;
        }

        /**
         * 是否正在忙
         * @return true 正忙   false 不忙
         */
        private boolean isBusy()
        {
            return isDoingCount.get() >= maxSyncCount;
        }

        /**
         * 检查机器是否还活着，如果死亡则恢复
         * @throws MachineException 
         */
        private void checkIsAliveAndRecover() throws MachineException
        {
            if (this.isAlive())
            {
                return;
            }
            // 正在恢复和机器的操作必须同步
            lock.lock();
            try
            {
                // 双重校验锁，提高性能
                if (this.isAlive())
                {
                    return;
                }
                recover(this);
            } finally
            {
                lock.unlock();
            }
        }

        /**
         * 恢复(使用原机器组装新的机器)
         * @param oldMachine
         * @throws MachineException 
         */
        private void recover(Machine oldMachine) throws MachineException
        {
            if (oldMachine == null)
            {
                throw new MachineException("旧机器为空，恢复失败！");
            }
            // 使用新得机器壳来包装原机器的零件
            Machine newMachine = new Machine(oldMachine);
            // 机器值变锁
            machine = newMachine;
            // 如果注入的解析器不为空则启动机器
            if (machine != null)
            {
                machine.startHandle();
            }
        }

        private boolean isWait()
        {
            return wait;
        }

        private boolean isChildWait()
        {
            return childWait;
        }

        /**
         * 重置最大同步数
         * @param maxSyncCount
         */
        private void reSetMaxSyncCount(int maxSyncCount)
        {
            lock.lock();
            try
            {
                AbstractFactory.this.maxSyncCount = maxSyncCount;
                if (maxSyncCount <= 1)
                {
                    isSingle.set(true);
                } else
                {
                    if (service == null)
                    {
                        // 新建子线程池
                        service = Executors.newCachedThreadPool();
                        ThreadPoolExecutor thisService = (ThreadPoolExecutor) service;
                        // 设置拒绝任务处理
                        thisService.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
                    }
                    isSingle.set(false);
                }
            } finally
            {
                lock.unlock();
            }
        }

        /**
         * 自省恢复
         * @author cuibo
         *
         */
        private class MachineUnCaughtExceptionHandler implements UncaughtExceptionHandler
        {

            @SuppressWarnings("unchecked")
            @Override
            public void uncaughtException(Thread t, Throwable e)
            {
                try
                {
                    recover((Machine) t);
                } catch (MachineException me)
                {
                    // 记录日志，机器自省恢复失败
                    me.printStackTrace();
                }
            }
        }

    }

    /**
     * 工厂工人
     * @author cuibo
     */
    final class Worker
    {

        /** 添加锁 */
        private Lock putLock;

        /** 添加条件 */
        private Condition putCondition;

        /** 等待锁 */
        private Lock waitLock;

        /** 等待条件 */
        private Condition waitCondition;

        /** 定时任务池 */
        private ExecutorService service;

        private Worker()
        {
            initWorkerResource();
        }

        private void setExecutorService(ExecutorService service)
        {
            if (service == null)
            {
                throw new RuntimeException("service不能为空！");
            }
            machine.service = service;
        }

        /**
         * 初始化工人必要资源
         */
        private void initWorkerResource()
        {
            this.putLock = new ReentrantLock();
            this.waitLock = new ReentrantLock();
            this.putCondition = putLock.newCondition();
            this.waitCondition = waitLock.newCondition();
            //  一个自动根据延迟时间清理过期产品， 一个自动根据延迟时间清理异常原料
            this.service = Executors.newFixedThreadPool(2);
        }

        private short getFactoryState()
        {
            if (machine.death)
            {
                return STATE_DOWN;
            }
            if (machine.wait)
            {
                return STATE_STOP;
            }
            if (stockQueue == null || stockQueue.isEmpty())
            {
                return machine.isDoingCount.get() > 0 ? STATE_WAIT_DO : STATE_WAIT;
            }
            return machine.isDoingCount.get() > 0 ? STATE_DO : STATE_WAIT;
        }

        /**
         * 重新提交出现异常的原料
         * @return
         * @throws FactoryException 
         */
        private boolean reHandExceptionStock() throws FactoryException
        {
            if (ThreadTempUtil.isEmpty(exceptionHandStockQueue))
            {
                throw new FactoryException("没有异常原料数据！");
            }
            // 检查原料合法性,该批原料也不允许重复
            Set<S> localSet = new HashSet<S>();
            for (HasHandStock<S, P> s : exceptionHandStockQueue)
            {
                checkStock(s.getStock());
                if (localSet.contains(s))
                {
                    throw new FactoryException("添加的原料中有不合法原料，原料重复！");
                }
                localSet.add(s.getStock());
            }
            checkCanWork();
            // 移除所有的异常原料
            for (Iterator<HasHandStock<S, P>> iterator = exceptionHandStockQueue.iterator(); iterator.hasNext();)
            {
                HasHandStock<S, P> local = iterator.next();
                iterator.remove();
                removeProductCauseByHasHandStockRemove(local);
            }
            // 重新添加
            for (S s : localSet)
            {
                addStockNoCheck(s);
            }
            return true;
        }
        
        /**
         * 重新提交出现异常的原料
         * @return
         * @throws FactoryException 
         */
        private boolean reHandExceptionStock(S stock) throws FactoryException
        {
            if (stock == null)
            {
                throw new FactoryException("指定的原料不能为空！");
            }
            if (ThreadTempUtil.isEmpty(exceptionHandStockQueue))
            {
                throw new FactoryException("没有异常原料数据！");
            }
            checkCanWork();
            // 移除所有的异常原料
            HasHandStock<S, P> found = null;
            for (Iterator<HasHandStock<S, P>> iterator = exceptionHandStockQueue.iterator(); iterator.hasNext();)
            {
                found = iterator.next();
                if (stock.equals(found.getStock()))
                {
                    checkStock(found.getStock());
                    iterator.remove();
                    break;
                }
            }
            if (found != null)
            {
                addStockNoCheck(found.getStock());
                removeProductCauseByHasHandStockRemove(found);
                return true;
            }
            return false;
        }


        /**
         * 工人开始工作
         */
        private void startWork()
        {
            // 启动机器
            startMachine();
            // 启动定时清理任务
            initScheduleTask();
        }

        /**
         * 启动机器
         */
        private void startMachine()
        {
            if (machine != null)
            {
                machine.startHandle();
            }
        }

        /**
        * 添加原料
        * @param entry
        * @throws FactoryException 
        */
        private boolean addStock(S entry) throws FactoryException
        {
            checkStock(entry);
            checkCanWork();
            return addStockNoCheck(entry);
        }

        /**
         * 添加原料
         * @param entry
         */
        private boolean addStockNoCheck(S entry)
        {
            if (stockQueue.add(entry))
            {
                addStockLatch(entry);
                return true;
            }
            return false;
        }

        /**
         * 添加原料检测器
         * @param entry
         */
        void addStockLatch(S entry)
        {
            stockLatch.put(entry, new CountDownLatch(1));
        }

        /**
         * 添加原料包
         * @param stockPackage
         * @throws FactoryException 
         */
        private boolean addStockPackage(StockPackage<S> stockPackage) throws FactoryException
        {
            if (stockPackage == null)
            {
                throw new FactoryException("原料包不能为空！");
            } else if (stockPackage.getId() == null)
            {
                throw new FactoryException("原料包ID不能为空！");
            }

            // 没有原料则不需要处理
            if (stockPackage.getStocks() == null || stockPackage.getStocks().isEmpty())
            {
                return false;
            }
            if (stockPackageLatch.containsKey(stockPackage.getId()))
            {
                throw new FactoryException("原料包重复！");
            }
            return addAllStock(stockPackage.getStocks(), stockPackage.getId(), true);
        }

        /**
         * 批量添加原料
         * @param entrys
         * @param stockPackageId  原料包ID   isStockPackage 为fasle时 stockPackageId可以为空
         * @param isStockPackage 是否是原料包添加
         * @throws FactoryException 
         */
        private boolean addAllStock(Collection<S> entrys, String stockPackageId, boolean isStockPackage)
                throws FactoryException
        {
            if (entrys == null || entrys.isEmpty())
            {
                throw new FactoryException("原料集合不能为空！");
            }
            // 检查原料合法性,该批原料也不允许重复
            Set<S> localSet = new HashSet<S>();
            for (S s : entrys)
            {
                checkStock(s);
                if (localSet.contains(s))
                {
                    throw new FactoryException("添加的原料中有不合法原料，原料重复！");
                }
                localSet.add(s);
            }
            checkCanWork();
            for (S s : entrys)
            {
                // 原料包添加需要添加原料包计数器
                if (isStockPackage)
                {
                    if (stockPackageLatch.containsKey(stockPackageId))
                    {
                        stockPackageLatch.get(stockPackageId).add(s);
                    } else
                    {
                        Set<S> queue = new ConcurrentSkipListSet<S>();
                        queue.add(s);
                        stockPackageLatch.put(stockPackageId, queue);
                    }
                }
                addStockNoCheck(s);
            }
            return true;
        }

        /**
         * 检查原料合法性
         * @param s
         * @throws FactoryException
         */
        void checkStock(S s) throws FactoryException
        {
            if (s == null)
            {
                throw new FactoryException("添加的原料中有不合法原料，如空原料！");
            }
            if (stockLatch.containsKey(s))
            {
                throw new FactoryException("添加的原料中有不合法原料，原料重复！");
            }
        }

        /**
         * 获取原料对应的产品
         * 如果机器还没有来得及解析完后文件，会阻塞该方法
         * @param s
         */
        private P getHandleProdct(S s)
        {
            HasHandStock<S, P> local = getHasHandStock(s);
            return local == null ? null : local.getProduct();
        }

        /**
	     * 获取原料对应的产品(设置超时)
	     * 如果机器还没有来得及解析完后文件，会阻塞该方法
	     * @param s
	     * @param wait
	     * @param unit
         * @throws TimeoutException 
	     */
	    private P getHandleProdct(S s, long wait, TimeUnit unit) throws TimeoutException
	    {
	        HasHandStock<S, P> local = getHasHandStock(s, wait, unit);
	        return local == null ? null : local.getProduct();
	    }

        /**
         * 获取原料对应的产品
         * 如果机器还没有来得及解析完后文件，会阻塞该方法
         * @param s
         */
        private HasHandStock<S, P> getHasHandStock(S s)
        {
            // 如果没有结果需要阻塞当前线程
            // 通过t读取对应的计数器
            CountDownLatch latch = stockLatch.get(s);
            if (latch == null)
            {
                HasHandStock<S, P> result = productMap.get(s);
                if (result != null)
                {
                    return result;
                }
                return null;
            }
            // 阻塞线程
            try
            {
                latch.await();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            // 移除该计数器
            if (latch.getCount() < 1)
            {
                stockLatch.remove(s);
                HasHandStock<S, P> result = productMap.get(s);
                if (result != null)
                {
                    return result;
                }
            }
            return null;
        }

        /**
         * 获取原料对应的产品(设置超时)
         * 如果机器还没有来得及解析完后文件，会阻塞该方法
         * @param s
         * @param wait
         * @param unit
         * @throws TimeoutException 
         */
        private HasHandStock<S, P> getHasHandStock(S s, long wait, TimeUnit unit) throws TimeoutException
        {
            // 如果没有结果需要阻塞当前线程
            // 通过t读取对应的计数器
            CountDownLatch latch = stockLatch.get(s);
            if (latch == null)
            {
                HasHandStock<S, P> result = productMap.get(s);
                if (result != null)
                {
                    return result;
                }
                return null;
            }
            // 阻塞线程
            try
            {
                latch.await(wait, unit);
                // 如果此时仍没有完成，则抛出等待超时异常
                if (latch.getCount() >= 1)
                {
                    throw new TimeoutException();
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            // 移除该计数器
            if (latch.getCount() < 1)
            {
                stockLatch.remove(s);
                HasHandStock<S, P> result = productMap.get(s);
                if (result != null)
                {
                    return result;
                }
            }
            return null;
        }

        /**
         * 等待原料加工完成
         * @param s
         */
        private void waitStockDown(S s)
        {
            CountDownLatch latch = stockLatch.get(s);
            if (latch == null)
            {
                // 没有对应的计数器，则认为已经完成
                return;
            }
            // 如果计数器的值已经小于1，则已经完成
            if (latch.getCount() < 1)
            {
                return;
            }
            // 阻塞线程
            try
            {
                latch.await();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }

        /**
         * 等待原料加工完成
         * @param s
         * @param wait
         * @param unit
         * @throws TimeoutException 
         */
        private void waitStockDown(S s, long wait, TimeUnit unit) throws TimeoutException
        {
            CountDownLatch latch = stockLatch.get(s);
            if (latch == null)
            {
                // 没有对应的计数器，则认为已经完成
                return;
            }
            // 如果计数器的值已经小于1，则已经完成
            if (latch.getCount() < 1)
            {
                return;
            }
            // 阻塞线程
            try
            {
                latch.await(wait, unit);
                // 如果此时仍没有完成，则抛出等待超时异常
                if (latch.getCount() >= 1)
                {
                    throw new TimeoutException();
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }

        /**
         * 等待原料包加工完成
         * @param stockPackageId
         */
        private void waitStockPackageDown(String stockPackageId)
        {
            // 没有原料包ID则认为完成
            if (!stockPackageLatch.containsKey(stockPackageId) || stockPackageLatch.get(stockPackageId) == null)
            {
                return;
            }
            for (S s : stockPackageLatch.get(stockPackageId))
            {
                // 原料包完成需要等待每个产品完成
                waitStockDown(s);
            }
        }

        /**
         * 等待原料包加工完成
         * @param stockPackageId
         * @param wait
         * @param unit
         * @throws TimeoutException 
         */
        private void waitStockPackageDown(String stockPackageId, long wait, TimeUnit unit) throws TimeoutException
        {
            // 没有原料包ID则认为完成
            if (!stockPackageLatch.containsKey(stockPackageId) || stockPackageLatch.get(stockPackageId) == null)
            {
                return;
            }
            // 转成纳秒
            long nanos = unit.toNanos(wait);
            for (S s : stockPackageLatch.get(stockPackageId))
            {
                long start = System.nanoTime();
                // 原料包完成需要等待每个产品完成
                waitStockDown(s, nanos, TimeUnit.NANOSECONDS);
                long waitTime = System.nanoTime() - start;
                // 剩余的等待时间
                nanos = nanos - waitTime;
                if (nanos < 0)
                {
                    throw new TimeoutException();
                }
            }
        }

        /**
         * 等待整个工厂处理完后当前所有原料
         */
        private void waitFactoryDown()
        {
            if (stockLatch.isEmpty())
            {
                return;
            }
            for (Entry<S, CountDownLatch> entry : stockLatch.entrySet())
            {
                CountDownLatch latch = entry.getValue();
                if (latch.getCount() < 1)
                {
                    continue;
                }
                // 原料包完成需要等待每个产品完成
                try
                {
                    latch.await();
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }

        /**
         * 等待整个工厂处理完后当前所有原料
         * @param wait
         * @param unit
         * @throws TimeoutException 
         */
        private void waitFactoryDown(long wait, TimeUnit unit) throws TimeoutException
        {
            if (stockLatch.isEmpty())
            {
                return;
            }
            // 转成毫秒
            long nanos = unit.toNanos(wait);
            for (Entry<S, CountDownLatch> entry : stockLatch.entrySet())
            {
                CountDownLatch latch = entry.getValue();
                if (latch.getCount() < 1)
                {
                    continue;
                }
                long start = System.nanoTime();
                // 原料包完成需要等待每个产品完成
                try
                {
                    latch.await(nanos, TimeUnit.NANOSECONDS);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                // 如果此时仍没有完成，则抛出等待超时异常
                if (latch.getCount() >= 1)
                {
                    throw new TimeoutException();
                }
                long waitTime = System.nanoTime() - start;
                // 剩余的等待时间
                nanos = nanos - waitTime;
                if (nanos < 0)
                {
                    throw new TimeoutException();
                }                
            }
        }

        /**
         * 检查原料是否加工完成
         * @param s
         */
        private boolean checkStockHasDown(S s)
        {
            // 如果没有结果需要阻塞当前线程
            // 通过t读取对应的计数器
            CountDownLatch latch = stockLatch.get(s);
            if (latch == null)
            {
                // 没有对应的计数器，则认为已经完成
                return true;
            }
            return latch.getCount() < 1;
        }

        /**
         * 检查原料是否加工完成
         * @param stockPackageId
         */
        private boolean checkStockPackageHasDown(String stockPackageId)
        {
            if (stockPackageLatch.containsKey(stockPackageId))
            {
                for (S s : stockPackageLatch.get(stockPackageId))
                {
                    // 只要有一个未完成，则任务该原料包未完成
                    if (!checkStockHasDown(s))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        /**
         * 暂停工作
         * @throws FactoryException 
         */
        private void stopHandle() throws FactoryException
        {
            checkCanWork();
            machine.stopHandle();
        }

        /**
         * 暂停工作，尽最大能力暂停子线程
         * @throws FactoryException
         */
        private void stopHandleNow() throws FactoryException
        {
            checkCanWork();
            machine.stopHandleNow();
        }

        /**
         * 重启工作
         * @throws FactoryException 
         */
        private void restartHandle() throws FactoryException
        {
            checkCanWork();
            machine.restartHandle();
        }

        /**
         * 重新设置最大同步数
         * @param maxSyncCount
         * @throws FactoryException
         */
        private void reSetMaxSyncCount(int maxSyncCount) throws FactoryException
        {
            try
            {
                if (maxSyncCount <= 0)
                {
                    maxSyncCount = 1;
                }
                checkCanWork();
                AbstractFactory.this.machine.reSetMaxSyncCount(maxSyncCount);
            } finally
            {
                // 不忙了可以唤醒机器
                if (!machine.isBusy())
                {
                    signPut();
                }
            }
        }

        /**
         * 关闭
         */
        private void shutDown()
        {
            // 关闭机器
            machine.shutDown();
            // 清楚所有原料产品等
            stockQueue = null;
            productMap = null;
            stockLatch = null;
            stockPackageLatch = null;
            hasHandStockQueue = null;
            isHandStockQueue = null;
            exceptionHandStockQueue = null;
            service.shutdown();
            factoryContext.shutDown();
        }

        /**
         * 获取第一个原料
         * @return
         */
        private S getStock()
        {
            // 如果机器最大并发数为1，则不需要工人监督机器的并发处理情况
            // 检查是否等待
            checkWait();
            if (!machine.isSingle.get())
            {
                // 检查是否繁忙
                checkBusy();
            }
            S result = null;
            try
            {
                result = getNextStock();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            // 需要再次校验是否被暂停，防止线程被空Queue阻塞
            checkWait();
            return result;
        }

        /**
         * 开始处理某一个原料
         */
        private boolean doStockStart(S stock)
        {
            if (isHandStockQueue.add(stock))
            {
                machine.getIsDoingCount().addAndGet(1);
                return true;
            }
            return false;
        }

        /**
         * 释放机器工作计数器，并唤醒等待
         */
        private void releaseMachineIsDoingCount()
        {
            // 计数器减一
            machine.getIsDoingCount().decrementAndGet();
            if (!machine.isBusy())
            {
                // 唤醒等待的线程
                signPut();
            }
        }

        /**
         * 清除整个工厂
         */
        private void clearFactory()
        {
            stockQueue.clear();
            stockLatch.clear();
            isHandStockQueue.clear();
            productMap.clear();
            hasHandStockQueue.clear();
            exceptionHandStockQueue.clear();
            stockPackageLatch.clear();
            stockPackageReRelation.clear();
            factoryContext.clear();
        }

        /**
         * 唤醒添加原料
         */
        private void signPut()
        {
            putLock.lock();
            try
            {
                putCondition.signalAll();
            } finally
            {
                putLock.unlock();
            }
        }

        /**
         * 唤醒等待
         */
        private void signWait()
        {
            waitLock.lock();
            try
            {
                waitCondition.signalAll();
            } finally
            {
                waitLock.unlock();
            }
        }

        /**
         * 检查子线程是否是等待
         */
        private void checkWait()
        {
            if (!machine.isWait())
            {
                return;
            }
            waitLock.lock();
            try
            {
                while (machine.isWait())
                {
                    waitCondition.await();
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            } finally
            {
                waitLock.unlock();
            }
        }

        private void checkBusy()
        {
            if (!machine.isBusy())
            {
                return;
            }
            // 检查是否繁忙（工人监督）
            putLock.lock();
            try
            {
                while (machine.isBusy())
                {
                    putCondition.await();
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            } finally
            {
                putLock.unlock();
            }
        }

        /**
         * 检查子线程是否是等待
         */
        private void checkChildWait()
        {
            waitLock.lock();
            try
            {
                while (machine.isChildWait())
                {
                    waitCondition.await();
                }
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            } finally
            {
                waitLock.unlock();
            }
        }

        /**
         * 存储消费后的产品
         * @param s
         * @param hasHandStock
         */
        private void addMachineResult(S s, HasHandStock<S, P> hasHandStock)
        {
            productMap.put(s, hasHandStock);
        }

        /**
         * 原料处理完成
         */
        private void doStockComplete(S stock, P result, Throwable cause)
        {
            try
            {
                doStockCompleteHook(stock, result, cause);
            } finally
            {
                // 保质期需要区分是产品保质期和异常原料保质期
                HasHandStock<S, P> hasHandStock = new HasHandStock<S, P>(System.currentTimeMillis(),
                        cause == null ? productExpirydate : exceptionExpirydate, stock, result, cause);
                // 工人将加工的结果存入工厂,不论有没有结果，都将hasHandStock存入productMap中
                worker.addMachineResult(stock, hasHandStock);
                if (cause != null)
                {
                    // 如果有异常需要存储异常原料
                    worker.addExceptionStock(hasHandStock);
                } else
                {
                    // 存储已经完成的原料
                    worker.addHasHandStock(hasHandStock);
                }
                // 移除正在处理的原料
                worker.removeIsHandStock(stock);
                // 将对应的计数器清零,并移除对应的计数器
                worker.removeCountDownLatch(stock);
                // 减少正在处理的个数，如果不忙则唤醒其他获取原料的线程
                worker.releaseMachineIsDoingCount();
            }
        }

        /**
         * 移除正在处理的原料
         * @param stock
         */
        private void removeIsHandStock(S stock)
        {
            isHandStockQueue.remove(stock);
        }

        /**
         * 移除原料
         * @param s
         * @return  移除成功的原料
         */
        private S removeStock(S s)
        {
            if (s == null)
            {
                return null;
            }
            if (stockQueue.remove(s))
            {
                // 如果stockPackageReRelation中包含对应的原料，则需要移除原料包里面的数据
                String packageId = stockPackageReRelation.remove(s);
                if (packageId != null)
                {
                    Set<S> localSet = stockPackageLatch.get(packageId);
                    if (localSet != null)
                    {
                        localSet.remove(s);
                        if (localSet.isEmpty())
                        {
                            stockPackageLatch.remove(packageId);
                        }
                    }
                }
                // 移除控制器
                stockLatch.remove(s);
                return s;
            }
            return null;
        }
        
        /**
         * 移除异常原料
         * @param s
         * @return  移除成功的原料
         */
        private S removeExceptionStock(S s)
        {
            if (s == null)
            {
                return null;
            }
            for (Iterator<HasHandStock<S, P>> iterator = exceptionHandStockQueue.iterator(); iterator.hasNext();)
            {
                HasHandStock<S, P> found = iterator.next();
                if (s.equals(found.getStock()))
                {
                    iterator.remove();
                    removeProductCauseByHasHandStockRemove(found);
                    return s;
                }
            }
            return null;
        }

        /**
         * 添加已经处理完的原料
         * @param hasHandStock
         */
        private void addHasHandStock(HasHandStock<S, P> hasHandStock)
        {
            hasHandStockQueue.add(hasHandStock);
        }

        /**
         * 清除指定原料的计数器
         * @param s
         */
        private void removeCountDownLatch(S s)
        {
            CountDownLatch latch = stockLatch.get(s);
            if (latch != null)
            {
                latch.countDown();
                stockLatch.remove(s);
            }
        }

        /**
         * 查看当前机器能否工作
         * @throws FactoryException 
         */
        void checkCanWork() throws FactoryException
        {
            if (machine == null)
            {
                throw new FactoryException("当前工厂没有生产机器！");
            }
            if (machine.death)
            {
                throw new MachineException("机器已经被关闭！");
            }
            // 检查机器状态，如果机器损坏，需要恢复
            machine.checkIsAliveAndRecover();
        }

        /**
         * 定时清理任务
         */
        private void initScheduleTask()
        {
            service.submit(new ProductClearTask());
            service.submit(new ExceptionClearTask());
        }

        /**
         * 添加出现异常的原料
         * @param hasHandStock
         */
        private void addExceptionStock(HasHandStock<S, P> hasHandStock)
        {
            exceptionHandStockQueue.add(hasHandStock);
        }

        /**
         * 异常原料清理
         * @author cuibo
         *
         */
        private class ProductClearTask implements Runnable
        {
            @Override
            public void run()
            {
                while (true)
                {
                    try
                    {
                        HasHandStock<S, P> local = hasHandStockQueue.take();
                        if (local != null)
                        {
                            removeProductCauseByHasHandStockRemove(local);
                        }
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }

        /**
         * 异常原料清理
         * @author cuibo
         *
         */
        private class ExceptionClearTask implements Runnable
        {
            @Override
            public void run()
            {
                while (true)
                {
                    try
                    {
                        HasHandStock<S, P> local = exceptionHandStockQueue.take();
                        if (local != null)
                        {
                            removeProductCauseByHasHandStockRemove(local);
                        }
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }

        /**
         * 由于已经完成的原料移除，移除产品数据 
         * @param handStock
         */
        private void removeProductCauseByHasHandStockRemove(HasHandStock<S, P> handStock)
        {
            // 移除产品中的map
            productMap.remove(handStock.getStock());
            // 如果stockPackageLatch中有对应的原料包信息，检查并移除
            String stockPageId = stockPackageReRelation.remove(handStock.getStock());
            if (stockPageId != null)
            {
                Set<S> localSet = stockPackageLatch.get(stockPageId);
                if (localSet != null)
                {
                    // 移除当前的原料
                    localSet.remove(handStock.getStock());
                    // 如果没有了，则移除对应的key
                    if (localSet.isEmpty())
                    {
                        stockPackageReRelation.remove(stockPageId);
                    }
                }
            }
        }

    }

    /**
     * 工厂上下文实现
     * @author cuibo
     *
     */
    final class FactoryContextImpl implements FactoryContext
    {

        private DelayCache<String, Object> cache = new DelayCache<String, Object>();

        @Override
        public Object getAttribute(String key)
        {
            return cache.getCache(key);
        }

        @Override
        public void setAttribute(String key, Object value)
        {
            cache.setCache(key, value, contextExpirydate);
        }

        @Override
        public void setAttribute(String key, Object value, long expirydate)
        {
            cache.setCache(key, value, expirydate);
        }

        @Override
        public Enumeration<String> getAttributeNames()
        {
            return cache.getCacheKeys();
        }

        @Override
        public Object removeAttribute(String key)
        {
            return cache.removeCache(key);
        }

        @Override
        public CreateAndExpiry getCreateAndExpiry(String key)
        {
            return cache.getCreateAndExpiry(key);
        }

        @Override
        public void shutDown()
        {
            cache.shutDown();
        }

        @Override
        public void clear()
        {
            cache.clear();
        }

    }

}
